package com.ermace.robo.jumper.game.Player.AI;

import java.util.List;

import com.ermace.robo.jumper.game.GameView;
import com.ermace.robo.jumper.game.Map;
import com.ermace.robo.jumper.game.GameObjects.GameObject;
import com.ermace.robo.jumper.game.Player.Position;
import com.ermace.robo.jumper.game.Player.Robot;
import com.ermace.robo.jumper.game.Player.Robot.VerticalOrientation;

public class AI_Hard extends AI {
	
	private float decision;
	private Map map;
	private GameObject objTarget = null;
	private GameObject standingOn = null;
	
	public AI_Hard(Robot robot, List<Robot> opponents, Map map) {
		super(robot, opponents);
		this.map = map;
	}
	
	@Override
	protected void calculateNextMove() {
		
		target = getClosestRobot();
		
		if (robot.isStandingOn(objTarget))
			objTarget = null;
		
		if (actionTime <= 0)
			decision = rand.nextFloat();
		
		boolean targetLeft = (getTarget().getPosition().getX() < robot.getPosition().getX());
		boolean targetUp = (getTarget().getPosition().getY() < robot.getPosition().getY());
		boolean targetEqual = (getTarget().getPosition().getY() == robot.getPosition().getY());
		
		boolean objLeft = false;
		boolean objRight = false;
		if (objTarget != null) {
			objLeft = objTarget.getRect().right < robot.getPosition().getX();
			objRight = objTarget.getRect().left > robot.getPosition().getX();
//			objUp = objTarget.getRect().top > robot.getPosition().getY() + Robot.RADIUS_HORIZONTAL / 2;
		}

		
		if (decision < 0.10 && robot.getVerticalOrientation() == VerticalOrientation.NONE)  // random jump ~10%
			robot.jump();
		if (decision < .8) { // something a little smarter ~70%
			if (objTarget == null && !targetIsUnderObject() ) {
//				if (targetLeft && !targetUp)
//					robot.move(LEFT);
//				else if (!targetLeft && targetUp)
//					robot.move(LEFT);
				if (targetEqual && decision < .55) {
					robot.jump();
				} else if (targetUp && decision < .6) {
					if ( getTarget().getPosition().getY() <= 
						(robot.getPosition().getY() - robot.getMaxJumpHeight() + Robot.RADIUS_HORIZONTAL) )
					{	// cannot jump on the robot directly
						objTarget = getGameObjectToJumpOn();
					} else {
						robot.jump();
					}
					
				}
				
				if (targetLeft ^ targetUp) {		// XOR = (x && !y) || (!x && y)
					robot.move(LEFT);
				}
				else
					robot.move(RIGHT);
			} else if (objTarget == null) {	//AI is standing on a object and the robot to kill is under the object.
				double distLeft = robot.getPosition().getX() - (standingOn.getPxPosition().getX() - standingOn.getPxLength() / 2);
				double distRight = (standingOn.getPxPosition().getX() + standingOn.getPxLength() / 2) - robot.getPosition().getX();
				
				if (distLeft < distRight)
					robot.move(LEFT);
				else
					robot.move(RIGHT);
			} else {
				if (objLeft)
					robot.move(LEFT);
				else if (objRight)
					robot.move(RIGHT);
				else
					robot.stop();
				
				if (robot.canJumpOn(objTarget))
					robot.jump();
			}
			
			if (actionTime <= 0)
				actionTime = rand.nextDouble() * 1.5 + 0.5;
		} else if (decision < .875) { // random move to left ~7.5%
			robot.move(LEFT);

			if (actionTime <= 0)
				actionTime = rand.nextDouble() * .35 + 0.5;
		} else if (decision < 0.95) {	// random move to right ~7.5%
			robot.move(RIGHT);
			
			if (actionTime <= 0)
				actionTime = rand.nextDouble() * .35 + 0.5;
		} else {		// random stop ~5%
			robot.stop();
			
			if (actionTime <= 0)
				actionTime = rand.nextDouble() * 0.25 + 0.25;
		}
	}
	
//	private void checkIncomingRobots() {			//TODO robot ontwijken
//		for (Robot toCheck: opponents) {
//			if (toCheck.isAlive() && toCheck != this.robot) {
//				toCheck.g
//			}
//		}
//	}
	
	private boolean targetIsUnderObject() {
		Position targetPos = getTarget().getPosition();
		boolean targetDown = (targetPos.getY() > robot.getPosition().getY());
		
		return (standingOn = robot.getObjectStandingOn()) != null
				&& targetDown && standingOn.contains(new Position(targetPos.getX(), standingOn.getPxPosition().getY()));
	}
	
	/**
	 * 
	 * @return 	The GameObject closest to the AI that the AI can jump on.
	 * 			Null if there is no such GameObject on the map.
	 */
	private GameObject getGameObjectToJumpOn() {
		double minDistance = 2 * GameView.SCREEN_WIDTH;
		double maxHeight = robot.getPosition().getY() + Robot.RADIUS_VERTICAL/2 - robot.getMaxJumpHeight();
		double distance;
		GameObject result = null;
		for (GameObject object: map.getObjects()) {
			if (object.getRect().top >= maxHeight) {
				distance = robot.getPosition().getDistanceTo(object.getPxPosition());
				minDistance = Math.min(minDistance, distance);
				if (minDistance == distance)
					result = object;
			}
		}
		
		return result;
	}
}
